/*
 * @描述: 
 * @创建者: kilomChou
 * @Date: 2021-04-11 17:21:46
 * @最后编辑: kilomChou
 * @LastEditTime: 2021-05-20 17:25:29
 */
import { RandUtil } from "../../util/RandUtil";
import World from "../world/World";
import Timer from "../../core/timer/Timer";
import Snake from "../snake/Snake";
import { IAIVal } from "../snake/SnakeAI";

export interface IBaseAI {
    snake: Snake,
    /** 优先级 (大的优先) 默认:0 */
    priority?: number
    /** 检测时间间隔 默认:0 */
    checkTime?: number | [number, number],
    /** 执行几率 默认:1 */
    aiChance?: number | [number, number],
    aiTime: number | [number, number]
}

export default abstract class BaseAI {

    constructor(obj: IBaseAI) {
        this.snake = obj.snake
        this.key = this.getKey()
        this.world = this.snake.world
        this.timer = this.snake.timer
        this.aiVal = this.snake.ai.aiVal
        this.timer.set(this.getKey(), 0)
        this.priority = obj.priority || 0
        this._checkTime = this.toMinMax(obj.checkTime || 0)
        this._checkChance = this.toMinMax(obj.aiChance || 1)
        this._aiTime = this.toMinMax(obj.aiTime)
    }

    /** 优先级 (大的优先) 默认:0 */
    priority: number

    readonly snake: Snake
    readonly timer: Timer
    readonly world: World
    readonly key: string
    readonly aiVal: IAIVal
    protected _checkTime: number[]
    protected _checkChance: number[]
    protected _aiTime: number[]
    protected _isAi: Boolean = false

    abstract getKey(): string
    abstract ai(dt: number): void
    abstract aiStart(): void
    abstract aiStop(): void

    protected get head() { return this.snake.head }


    protected toMinMax(v: number | number[]) {
        return v instanceof Array ? v : [v, v]
    }

    protected setAiTime(time: number = RandUtil.rand2(this._aiTime)) {
        this.timer.set(this.key, time)
    }

    protected recheck() {
        this._isAi = false
        this.timer.set(this.key, RandUtil.rand2(this._checkTime))
    }

    check() {
        if (this._isAi) {
            this.ai(this.world.dt)
            this.timer.check(this.key, () => {
                this.aiStop()
                this.recheck()
            })
        } else {
            this.timer.check(this.key, () => {
                if (RandUtil.chance(RandUtil.rand2(this._checkChance))) {
                    this._isAi = true
                    this.aiStart()
                    if (this._isAi) {
                        this.setAiTime()
                    }
                } else {
                    this.recheck()
                }
            })
        }
    }
}